/*
管理员账号：Admin
管理员密码：AdminPassport
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#define EXIT 0
#define INIT 1
#define ADMIN 2
#define READER 3
#define AD_ADD 4
#define AD_DELETE 5
#define AD_MODIFY 6
#define AD_ENQUIRE 7
#define AD_SORT 8
#define AD_BORROW 9
#define AD_RETURN 10
#define AD_COUNT 11
#define AD_PRINT 12
#define AD_COMFIRM 13
#define RE_ENQUIRE 14
#define RE_SORT 15
#define RE_BORROW 16
#define RE_RETURN 17
#define RE_COUNT 18
#define RE_PRINT 19
#define PUTS1                       \
    {                               \
        puts("\nAdmin Or Reader?"); \
        puts("1:Admin");            \
        puts("2:Reader");           \
        puts("0:Exit");             \
    }
#define PUTS2                            \
    {                                    \
        puts("\n请选择你要进行的操作:"); \
        puts("1:Add");                   \
        puts("2:Delete");                \
        puts("3:Modify");                \
        puts("4:Enquire");               \
        puts("5:Sort");                  \
        puts("6:Borrow");                \
        puts("7:Return");                \
        puts("8:Count");                 \
        puts("9:Print");                 \
        puts("10:Affirm");               \
        puts("0:Exit");                  \
    }
#define PUTS3                    \
    {                            \
        puts("\n是否继续操作?"); \
        puts("1:Continue");      \
        puts("0:Exit");          \
    }
#define PUTS4                        \
    {                                \
        puts("\n想要修改什么信息?"); \
        puts("1:Name");              \
        puts("2:Author");            \
        puts("3:Press");             \
        puts("4:In year:");          \
        puts("5:In month");          \
        puts("6:In day");            \
        puts("7:Stock");             \
        puts("8:Borrows");           \
        puts("0:exit");              \
    }
#define PUTS5                            \
    {                                    \
        puts("\n请选择你要进行的操作:"); \
        puts("1:Enquire");               \
        puts("2:Sort");                  \
        puts("3:Borrow");                \
        puts("4:Return");                \
        puts("5:Count");                 \
        puts("6:Print");                 \
        puts("0:exit");                  \
    }

typedef struct _date //入库日期
{
    int year, month, day;
} Date;
typedef struct _book //图书信息
{
    char name[40], author[40], press[40];
    Date intime;
    int stock, borrows;
    struct _book *next;
} Book, *BookList;
typedef struct _reader //读者信息
{
    char account[200], passport[200];
    int all_borrows;
    struct _reader *next;
} Reader, *ReaderList;

BookList inputdata();         //图书信息导入
int init();                   //初始化
int admin_init();             //管理员初始化
int admin();                  //管理员操作
BookList ad_add(BookList);    //录入
BookList ad_delete(BookList); //删除
void ad_modify(BookList);     //修改
void ad_enquire(BookList);    //查询
void ad_borrow(BookList);     //借书
void ad_return(BookList);     //还书
void ad_count(BookList);      //统计
void ad_print(BookList);      //输出
ReaderList reader_init();     //读者初始化
int reader();                 //读者操作

int main()
{
    BookList list = inputdata();
    ReaderList me = NULL;
    int state = 1;

    while (1)
    {
        int op;
        switch (state)
        {
        case EXIT:
            puts("\nGoodbye!");
            return 0;
            break;
        case INIT:
            state = init();
            break;
        case ADMIN:
            state = admin_init();
            break;
        case AD_ADD:
            list = ad_add(list);
            state = admin();
            break;
        case AD_DELETE:
            list = ad_delete(list);
            state = admin();
            break;
        case AD_MODIFY:
            ad_modify(list);
            state = admin();
            break;
        case AD_ENQUIRE:
            ad_enquire(list);
            state = admin();
            break;
        case AD_SORT:
            //不想写排序
            state = admin();
            break;
        case AD_BORROW:
            ad_borrow(list);
            state = admin();
            break;
        case AD_RETURN:
            ad_return(list);
            state = admin();
            break;
        case AD_COUNT:
            ad_count(list);
            state = admin();
            break;
        case AD_PRINT:
            ad_print(list);
            state = admin();
            break;
        case READER:
            me = reader_init();
            state = reader();
            break;
        case RE_ENQUIRE:
            ad_enquire(list);
            state = reader();
            break;
        case RE_SORT:
            //不想写排序
            state = reader();
            break;
        case RE_BORROW:
            ad_borrow(list);
            me->all_borrows++;
            state = reader();
            break;
        case RE_RETURN:
            ad_return(list);
            me->all_borrows--;
            state = reader();
            break;
        case RE_COUNT:
            printf("All_borrows: %d\n", me->all_borrows);
            state = reader();
            break;
        case RE_PRINT:
            ad_print(list);
            state = reader();
            break;
        default:
            break;
        }
    }

    return 0;
}

BookList inputdata()
{
    BookList q = NULL, preq = q;
    FILE *fp;
    char laji[200];
    if (!(fp = fopen("book.dat", "r")))
    {
        puts("无法导入文件 book.dat !");
    }
    else
    {
        fgets(laji, 200, fp);
        while (1)
        {
            BookList p = (BookList)malloc(sizeof(Book));
            if (fscanf(fp, "%s", p->name) == EOF)
                break;
            fscanf(fp, "%s%s%d-%d-%d%d%d", p->author, p->press, &p->intime.year, &p->intime.month, &p->intime.day, &p->stock, &p->borrows);
            p->next = NULL;
            if (q == NULL) //如果q是头节点
                q = preq = p;
            else
            {
                preq->next = p;
                preq = p;
            }
        }
        puts("\n文件导入成功!\n");
    }
    return q;
}
int init()
{
    int op;
    puts("欢迎进入图书信息管理系统!");
    PUTS1

    while (scanf("%d", &op) != 1 || (op != 0 && op != 1 && op != 2))
    {
        char laji[200];
        fgets(laji, 200, stdin);
        puts("请输入数字!");
        PUTS1
    }
    if (op == 0)
        return EXIT;
    else if (op == 1)
        return ADMIN;
    else if (op == 2)
        return READER;
    else
        return assert(op == 0), 0;
}
int admin_init()
{
    int op;
    char account[200], passport[200];
    puts("请输入账号密码，输入 Exit 可结束程序");
    printf("Account: ");
    scanf("%s", account);
    printf("Passport: ");
    scanf("%s", passport);
    if (strcmp(account, "Exit") == 0)
        return EXIT;
    if (strcmp(account, "Admin") == 0 && strcmp(passport, "AdminPassport") == 0)
    {
        PUTS2
        while (scanf("%d", &op) != 1 || (!(0 <= op && op <= 10)))
        {
            char laji[200];
            fgets(laji, 200, stdin);
            puts("请输入数字!");
            PUTS2
        }
        if (op == 0)
            return EXIT;
        return op + 3;
    }
    else
        return printf("\n账号或者密码错误!\n"), ADMIN;
}
int admin()
{
    int op;
    PUTS3
    while (scanf("%d", &op) != 1 || (op != 0 && op != 1))
    {
        char laji[200];
        fgets(laji, 200, stdin);
        puts("请输入数字!");
        PUTS3
    }
    if (op == 0)
        return EXIT;
    PUTS2
    while (scanf("%d", &op) != 1 || (!(0 <= op && op <= 10)))
    {
        char laji[200];
        fgets(laji, 200, stdin);
        puts("请输入数字!");
        PUTS2
    }
    if (op == 0)
        return EXIT;
    return op + 3;
}
BookList ad_add(BookList T)
{
    BookList p = T, q;
    q = (BookList)malloc(sizeof(Book));
    char temp[200], laji[20];
    gets(laji);

    puts("请输入图书信息:");
    printf("Name: ");
    gets(temp);
    strcpy(q->name, temp);
    printf("Author: ");
    gets(temp);
    strcpy(q->author, temp);
    printf("Press: ");
    gets(temp);
    strcpy(q->press, temp);
    printf("Year, Month, Day: ");
    scanf("%d%d%d", &q->intime.year, &q->intime.month, &q->intime.day);
    printf("Num: ");
    scanf("%d", &q->stock);
    q->borrows = 0;
    q->next = NULL;

    if (p == NULL)
        return q;
    while (p->next != NULL)
        p = p->next;
    p->next = q;
    return T;
}
BookList ad_delete(BookList T)
{
    if (T == NULL)
    {
        puts("\nEmpty!");
        return NULL;
    }
    else
    {
        int flag = 0;
        char na[200], laji[20];
        gets(laji);
        BookList p = T, q = T;
        printf("请输入想要删除的书名: ");
        gets(na);
        while (p != NULL)
        {
            if (strcmp(p->name, na) == 0)
            {
                flag = 1;
                break;
            }
            q = p;
            p = p->next;
        }
        if (!flag)
        {
            puts("No such book!\n");
            return T;
        }
        else
            puts("Work!");
        if (p == T)
            return p->next;
        q->next = p->next;
        free(p);
        return T;
    }
}

void ad_modify(BookList T)
{
    if (T == NULL)
    {
        puts("\nEmpty!");
        return;
    }
    else
    {
        int flag = 0, op;
        char na[200], laji[20];
        gets(laji);
        BookList p = T;
        printf("input name: ");
        gets(na);
        while (p != NULL)
        {
            if (strcmp(p->name, na) == 0)
            {
                flag = 1;
                break;
            }
            p = p->next;
        }
        if (!flag)
        {
            puts("No such book!\n");
            return;
        }
        else
        {
            PUTS4
            scanf("%d", &op);
            if (op == 1)
            {
                printf("new name:");
                scanf("%s", p->name);
            }
            else if (op == 2)
            {
                printf("new author:");
                scanf("%s", p->author);
            }
            else if (op == 3)
            {
                printf("new press:");
                scanf("%s", p->press);
            }
            else if (op == 4)
            {
                printf("new in year:");
                scanf("%d", &p->intime.year);
            }
            else if (op == 5)
            {
                printf("new in month:");
                scanf("%d", &p->intime.month);
            }
            else if (op == 6)
            {
                printf("new in day:");
                scanf("%d", &p->intime.day);
            }
            else if (op == 7)
            {
                printf("new stock:");
                scanf("%d", &p->stock);
            }
            else if (op == 8)
            {
                printf("new borrows:");
                scanf("%d", &p->borrows);
            }
            puts("Work!");
        }
    }
}

void ad_enquire(BookList T)
{
    if (T == NULL)
    {
        puts("\nEmpty!");
        return;
    }
    else
    {
        int flag = 0, op;
        char na[200], laji[20];
        gets(laji);
        BookList p = T;
        printf("请输入想要查询的书名 : ");
        gets(na);
        while (p != NULL)
        {
            if (strcmp(p->name, na) == 0)
            {
                flag = 1;
                break;
            }
            p = p->next;
        }
        if (!flag)
        {
            puts("No such book!\n");
            return;
        }
        else
        {
            printf("Name: %s\nAuthor: %s\nPress: %s\nIntime: %04d-%02d-%02d\nStock: %d\nBorrows: %d\n",
                   p->name, p->author, p->press, p->intime.year, p->intime.month, p->intime.day, p->stock, p->borrows);
        }
    }
}

void ad_borrow(BookList T)
{
    int flag = 0, op;
    char na[200], laji[20];
    gets(laji);
    BookList p = T;
    printf("请输入想要借阅的图书的书名: ");
    gets(na);
    while (p != NULL)
    {
        if (strcmp(p->name, na) == 0)
        {
            flag = 1;
            break;
        }
        p = p->next;
    }
    if (!flag)
    {
        puts("No such book!\n");
        return;
    }
    else
    {
        if (p->borrows == p->stock)
        {
            puts("此书可借阅量为0!");
        }
        else
        {
            p->borrows++;
            puts("Work!");
        }
    }
}

void ad_return(BookList T)
{
    int flag = 0, op;
    char na[200], laji[20];
    gets(laji);
    BookList p = T;
    printf("请输入归还的书名: ");
    gets(na);
    while (p != NULL)
    {
        if (strcmp(p->name, na) == 0)
        {
            flag = 1;
            break;
        }
        p = p->next;
    }
    if (!flag)
    {
        puts("No such book!\n");
        return;
    }
    else
    {
        p->borrows--;
    }
}

void ad_count(BookList T)
{
    int cnt = 0;
    BookList p = T;
    while (p != NULL)
    {
        cnt += p->borrows;
        p = p->next;
    }
    printf("All borrows: %d\n", cnt);
}

void ad_print(BookList T)
{
    BookList p = T;
    if (p == NULL)
    {
        puts("\nEmpty!");
    }
    else
    {
        printf("   Name         Author       Press          Intime       Stock     Borrows\n");
        while (p != NULL)
        {
            printf("   %-10s    %-10s   %-10s   %04d-%02d-%02d      %-5d     %-5d\n",
                   p->name, p->author, p->press, p->intime.year, p->intime.month, p->intime.day, p->stock, p->borrows);
            p = p->next;
        }
        FILE *fp;
        if (!(fp = fopen("book.dat", "w")))
            puts("open error");
        p = T;
        fprintf(fp, "   Name         Author       Press          Intime      Stock     Borrows\n");
        while (p != NULL)
        {
            fprintf(fp, "   %-10s    %-10s   %-10s   %04d-%02d-%02d      %-5d     %-5d\n",
                    p->name, p->author, p->press, p->intime.year, p->intime.month, p->intime.day, p->stock, p->borrows);
            p = p->next;
        }
        puts("成功导出到文件 book.dat! ");
    }
}

ReaderList reader_init()
{
    ReaderList p = (ReaderList)malloc(sizeof(Reader));
    puts("请输入读者的账号密码");
    printf("Account: ");
    scanf("%s", p->account);
    printf("Passport: ");
    scanf("%s", p->passport);
    return p;
}
int reader()
{
    int op;
    PUTS3
    while (scanf("%d", &op) != 1 || (op != 0 && op != 1))
    {
        char laji[200];
        fgets(laji, 200, stdin);
        puts("请输入数字!");
        PUTS3
    }
    if (op == 0)
        return EXIT;
    PUTS5
    while (scanf("%d", &op) != 1 || (!(0 <= op && op <= 6)))
    {
        char laji[200];
        fgets(laji, 200, stdin);
        puts("请输入数字!");
        PUTS5
    }
    if (op == 0)
        return EXIT;
    else
        return op + 13;
}
